#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>		// define file operation

// For Linux 2.4 Kernel
// #include <linux/conifg.h> 


#ifdef CONFIG_SMP
	#define __SMP__
#endif

#define CDATA_MAJOR 121
#define CDATA_DEV_NAME "cdata"
#define CDATA_DEBUG_PREFIX "cdata:"

////////////////////////////////////////////////////
// Driver Function Declartion
///////////////////////////////////////////////////
static int cdata_open(struct inode* inode_ptr, struct file* file_ptr);
static int cdata_release(struct inode* inode_ptr, struct file* file_ptr);
static ssize_t cdata_write(struct file * file_ptr, const char* input_data, size_t size, loff_t * offset);


////////////////////////////////////////////////////
// Driver Data Structure Declartion
///////////////////////////////////////////////////


static struct file_operations cdata_fops = {
	write: cdata_write,
	open: cdata_open,
	release: cdata_release,
}; 	// Step 1: create file operation

// Step 2: implement system call

static int cdata_open(struct inode* inode_ptr, struct file* file_ptr){
	printk(KERN_ALERT CDATA_DEBUG_PREFIX "open cdata device....\r\n");
	printk(KERN_ALERT CDATA_DEBUG_PREFIX "fs_ptr = %x\r\n",(unsigned int)file_ptr);

	return 0;
} 

static int cdata_release(struct inode* inode_ptr, struct file* file_ptr){
	printk(KERN_ALERT CDATA_DEBUG_PREFIX "release cdata device....\r\n");
	return 0;
}

static ssize_t cdata_write(struct file * file_ptr, const char* input_data, size_t size, loff_t * offset){
	printk(KERN_ALERT CDATA_DEBUG_PREFIX  "write data\r\n");
	return 0;
}

int my_init_module(void){
	printk(KERN_ALERT "Hello, World.\n");

	// Step 3: Register driver
	if( register_chrdev(CDATA_MAJOR,CDATA_DEV_NAME,&cdata_fops) ){
		printk(KERN_ALERT CDATA_DEBUG_PREFIX "register failed!\r\n");
	}

//	------------ Kernel schedule test ------------
//	while(1){
//		schedule();
//	}
//	------------ Kernel schedule test ------------

	return 0;
}

void my_cleanup_module(void){
	printk( KERN_ALERT "Goodbye...\n");
	unregister_chrdev(CDATA_MAJOR,CDATA_DEV_NAME);
	printk(KERN_ALERT CDATA_DEBUG_PREFIX "unregister\r\n");
	return;
}

module_init(my_init_module);
module_exit(my_cleanup_module);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jollen <Jollen@o3.net>");
MODULE_DESCRIPTION("A Linux kernel module programming example");
MODULE_SUPPORTED_DEVICE("testdevice");


